home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MAIL.SWG / 0020_QWK Conf Member listing.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  25KB  |  580 lines

  1.  
  2. {***********************************************************************}
  3. {$M 16384,0,0}                  { Save memory for Calling PKUNZIP.      }
  4. PROGRAM NMembers;               { May 16/94, Greg Estabrooks.           }
  5. USES
  6.      DOS;
  7. CONST
  8.      Ver      = 'V0.2ß';        { Current Version of program.           }
  9.      ProgTitle= 'NMem '+Ver+'- Conference Member Tracking Program. ';
  10.      Author   = 'CopyRight (C) 1994, Greg Estabrooks.';
  11. TYPE
  12.     Direction = (Left,Right);
  13.  
  14.     MsgDHdr = RECORD            { Structre of QWK Message Header.       }
  15.                Status    :CHAR;
  16.                MNum      :ARRAY[1..7] OF CHAR;
  17.                Date      :ARRAY[1..8] OF CHAR;
  18.                Time      :ARRAY[1..5] OF CHAR;
  19.                MTo       :ARRAY[1..25] OF CHAR;
  20.                MFrom     :ARRAY[1..25] OF CHAR;
  21.                MSubj     :ARRAY[1..25] OF CHAR;
  22.                Pass      :ARRAY[1..12] OF CHAR;
  23.                MRefer    :ARRAY[1..8] OF CHAR;
  24.                NChunks   :ARRAY[1..6] OF CHAR;
  25.                Active    :CHAR;
  26.                MConf     :WORD;
  27.                Fill      :ARRAY[1..3] OF CHAR;
  28.              END;{MsgDHdr}
  29.  
  30.     NDXType = RECORD
  31.                 Offset :LONGINT;
  32.                 Misc   :BYTE;
  33.               END;
  34.  
  35.     MessInfType = RECORD
  36.                    Name  :STRING[25];   { Name of person message FROM.  }
  37.                    Origin:STRING[80];   { Origin line from message.     }
  38.                   END;
  39.  
  40. VAR
  41.   QWKName :STRING[128];         { QWK File to process.                  }
  42.   OutFile :STRING[128];         { File to place new member names.       }
  43.   WorkDir :STRING[128];         { Holds the name of our work directory. }
  44.   OutHan  :TEXT;                { File handle for output file.          }
  45.   MessDat :FILE;                { File handle for MESSAGES.DAT.         }
  46.  
  47.   NumMess :WORD;                { Number of messages in conference.     }
  48.   NewMems :WORD;                { Number of new members found.          }
  49.   NumFound:WORD;                { Holds number of different names found.}
  50.  
  51.   fOfs    :ARRAY[1..500] OF LONGINT;{ Holds offset info from NDX file.  }
  52.   FInf    :ARRAY[1..500] OF MessInfType;
  53.  
  54. FUNCTION PadStr( Dir :Direction; Str2Pad :STRING; Til :BYTE;
  55.                                                  Ch :CHAR ) :STRING;
  56.                          { Function to pad a string with 'Ch' until it  }
  57.                          { is 'Til' long.                               }
  58. VAR
  59.    Temp :STRING;                { Temporary String info.                }
  60. BEGIN
  61.   Temp := Str2Pad;              { Initialize 'Temp' to users string.    }
  62.   IF Length(Temp) < Til THEN    { If its smaller than 'Til' add padding.}
  63.   WHILE (Length(Temp) < Til) DO { Loop until proper length reached.     }
  64.    BEGIN
  65.      CASE Dir OF
  66.       Right :Temp := Temp + Ch; { If Right then add to end of string.   }
  67.       Left  :Temp := Ch + Temp; { If Left then add to begining.         }
  68.      END;
  69.    END;
  70.   PadStr := Temp;               { Return proper result.                 }
  71. END;
  72.  
  73. PROCEDURE InitVars;
  74.                         { Procedure to initialize program variables.    }
  75. VAR
  76.    Temp :STRING[4];             { Temporary String value.               }
  77. BEGIN
  78.   FillChar(FInf,SizeOf(FInf),#0); { Clear FInf.                         }
  79.   NumMess := 0;                 { Clear number of messages.             }
  80.   NewMems := 0;                 { Clear number of new members found.    }
  81.   QWKName := ParamStr(1);       { Get QWK Name from command line.       }
  82.   NumFound := 1;                { Initialize 'NumFound.'                }
  83.   Temp := ParamStr(2);          { Get Conf Number from command line.    }
  84.   OutFile := 'CNF'+PadStr(Left,Temp,5,'0')+'.LST';
  85.                                 { Prepare output file name.             }
  86.  
  87.   GetDir(0,WorkDir);            { Save current directory.               }
  88.   IF WorkDir[Length(WorkDir)] = '\' THEN
  89.    WorkDir := WorkDir +'NMEM'
  90.   ELSE
  91.    WorkDir := WorkDir +'\NMEM';
  92. END;{InitVars}
  93.  
  94. PROCEDURE Syntax_Error;
  95.                        { Display proper command line syntax to user.    }
  96. BEGIN
  97.   Writeln;                      { Skip a line.                          }
  98.   Writeln(
  99.      'Syntax: NMEM [drive]:[path]PacketName ConfNum');
  100.                                 { Show syntax for user.                 }
  101.   Writeln;                      { Skip a line.                          }
  102.                                 { Show an example usage.                }
  103.   Writeln('EXAMPLE : NMEM C:\QWK\MYBBS.QWK 123');
  104.   Writeln(' Scans MYBBS.QWK and generates CNF00123.LST');
  105.   Halt(1);                      { Halt program with and ERRORLEVEL of 1.}
  106. END;{Syntax_Error}
  107.  
  108. FUNCTION fExist( FName :STRING ) :BOOLEAN;
  109.                         { Routine to determine whether or not 'FName'   }
  110.                         { really exists.                                }
  111. BEGIN
  112.   fExist := (fSearch(FName,'') <> '');
  113. END;{fExist}
  114.  
  115. FUNCTION DirExist( DName :STRING ) :BOOLEAN;
  116.                          { Routine to determine whether or not the      }
  117.                          { Directory 'DName' exists.                    }
  118. VAR
  119.    DirInf :SearchRec;           { Hold info if dir found.               }
  120. BEGIN
  121.   FindFirst(DName,Directory,DirInf);
  122.   DirExist := (DosError = 0);
  123. END;{DirExist}
  124.  
  125. PROCEDURE DelWorkDir;
  126.                          { Routine to delete files in the work directory}
  127.                          { and them remove the directory.               }
  128. VAR
  129.    FileInf :SEARCHREC;          { Holds file names for erasure.         }
  130.    fVar    :FILE;               { Handle of file to delete.             }
  131. BEGIN
  132.   FindFirst(WorkDir+'\*.*',Archive,FileInf); { Get File Name.           }
  133.   WHILE (DosError = 0) DO       { Loop until all file names read.       }
  134.   BEGIN
  135.     Assign(fVar,WorkDir+'\'+FileInf.Name);
  136.                                 { Assign file name to handle.           }
  137.     Erase(fVar);                { Erase File.                           }
  138.     FindNext(FileInf);          { Get next file name.                   }
  139.   END;
  140. END;{DelWorkDir}
  141.  
  142. PROCEDURE OpenPacket( QName :STRING );
  143.                          { Routine open mail packets.                   }
  144. VAR
  145.    PKPath :STRING;              { Holds location of PKUNZIP.EXE         }
  146. BEGIN
  147.   IF NOT DirExist(WorkDir) THEN { If dir doesn't exist then make it.    }
  148.    BEGIN
  149.     {$I-}                       { Turn I/O checking off.                }
  150.     MKDir(WorkDir);             { Create our work directory.            }
  151.     {$I+}                       { Turn I/O checking off.                }
  152.  
  153.     IF IOResult <>0 THEN        { If I/O error then                     }
  154.      BEGIN                      { Display error message.                }
  155.       Writeln('Error creating work directory',^G);
  156.       Halt(1);                  { Now halt program.                     }
  157.      END;
  158.  
  159.    END
  160.   ELSE
  161.    DelWorkDir;                  { If it does exist then clear it.       }
  162.  
  163.   IF NOT fExist('PKUNZIP.EXE') THEN { If it's not in the current dir    }
  164.    BEGIN                        { then search the %PATH%.               }
  165.     PKPath := fSearch('PKUNZIP.EXE',GetEnv('PATH'));
  166.     IF PKPath = '' THEN         { If it's nowhere to be found then      }
  167.      BEGIN                      { Display error message.                }
  168.       Writeln('Cannot find PKUNZIP.EXE!',^G);
  169.       Writeln('It must be located either in the ',
  170.                  'current directory or along your %PATH%');
  171.       Halt(1);                  { Now halt program.                     }
  172.      END;
  173.    END;
  174.  
  175.   SwapVectors;                  { Swap to proper Interrupt vectors.     }
  176.   Exec(GetEnv('COMSPEC'),'/C '+PKPath+' '+QWKName+' '+WorkDir+' >NUL');
  177.   SwapVectors;                  { Swap em back.                         }
  178.  
  179.   IF DosError <> 0 THEN         { If there was an 'Exec' error then     }
  180.    BEGIN                        { Display error message.                }
  181.     Writeln('Error #',DosError,' occured executing ',PKPath,^G);
  182.     Halt(1);                    { Now Halt program.                     }
  183.    END;
  184.  
  185.   IF DosExitCode <> 0 THEN      { Check for a program error.            }
  186.    Writeln(PKPath,' returned an ERRORLEVEL of ',DosExitCode,^G);
  187. END;{OpenPacket}
  188.  
  189. FUNCTION NotNumber( NumStr :STRING ) :BOOLEAN;
  190.                          { Routine to determine whether or not 'NumStr' }
  191.                          { is a valid number.                           }
  192.                          { Returns TRUE if not a number FALSE if a num. }
  193. VAR
  194.    Result :BOOLEAN;             { Holds Function result.                }
  195.    StrPos :BYTE;                { Position withing string.              }
  196. BEGIN
  197.   Result := FALSE;              { Defaults to false.                    }
  198.   FOR StrPos := 1 TO Length(NumStr) DO { Loop through entire string.    }
  199.    IF NOT (NumStr[StrPos] IN
  200.             ['0','1','2','3','4','5','6','7','8','9']) THEN
  201.      Result := TRUE;
  202.  
  203.   NotNumber := Result;          { Return proper result.                 }
  204. END;{NotNumber}
  205.  
  206. FUNCTION ReadNDX :BOOLEAN;
  207.                          { Routine to read proper NDX file for conference.}
  208. VAR
  209.    Result :BOOLEAN;             { Holds Function result.                }
  210.    NDX    :FILE;                { File handle for NDX file.             }
  211.    Info   :NDXType;             { Hold info read from NDX file.         }
  212.    NumRead:WORD;                { Holds number of bytes read from NDX.  }
  213. BEGIN
  214.   Result := TRUE;               { Default to success.                   }
  215.   Assign(NDX,WorkDir+'\'+PadStr(Left,ParamStr(2),3,'0')+'.NDX');
  216.   {$I-}                         { Turn off I/O checking.                }
  217.   Reset(NDX,1);                 { Open NDX for reading.                 }
  218.   {$I+}                         { Turn on I/O checking.                 }
  219.   WHILE NOT EOF(NDX) DO         { Loop until end of file.               }
  220.    BEGIN
  221.      BlockRead(NDX,Info,SizeOf(Info),NumRead); { Read offset of message.}
  222.      IF (NumRead = Sizeof(Info)) AND (NumMess <501) THEN
  223.                                 { If proper amount read then            }
  224.       BEGIN                     { Convert it to a proper LONGINT.       }
  225.         INC(NumMess);           { Increase message total.               }
  226.                                 { Now convert offset.                   }
  227.         fOfs[NumMess] := ((Info.Offset AND NOT $FF000000) OR $00800000)
  228.                           SHR (24 - ((Info.Offset SHR 24) AND $7F));
  229.         fOfs[NumMess] := (fOfs[NumMess]-1) SHL 7;
  230.       END
  231.      ELSE
  232.       Result := FALSE;          { Otherwise return FALSE result.        }
  233.    END;
  234.   Close(NDX);                   { Close NDX File.                       }
  235.   ReadNDX := Result;            { Return proper result.                 }
  236. END;{ReadNDX}
  237.  
  238. PROCEDURE RemoveSpaces(VAR Str2Rem :STRING);
  239.                          { Routine to remove any spaces from 'Str2Rem'. }
  240. VAR
  241.    StrPos :WORD;                { Position within string.               }
  242.    Temp   :STRING;              { Temporary string work space.          }
  243. BEGIN
  244.   Temp := '';                   { Clear string.                         }
  245.   FOR StrPos := 1 TO Length(Str2Rem) DO { Loop through all characters.  }
  246.    IF Str2Rem[StrPos] <> #32 THEN   { If its not a space then           }
  247.     Temp := Temp + Str2Rem[StrPos]; { add it to our string.             }
  248.  
  249.   Str2Rem := Temp;              { Return newly changed string.          }
  250. END;{RemoveSpaces}
  251.  
  252. FUNCTION Compare( Str1,Str2 :STRING ) :BOOLEAN;
  253.                          { Routine to compare to strings after removing }
  254.                          { any spaces from it.Case INSENSITIVE.         }
  255. VAR
  256.    Result :BOOLEAN;             { Result from comparing.                }
  257.    StrPos :BYTE;                { Position within 2 strings.            }
  258. BEGIN
  259.   Result := TRUE;               { Default result to TRUE.               }
  260.   RemoveSpaces(Str1);           { Trim spaces from the strings.         }
  261.   RemoveSpaces(Str2);
  262.   IF Length(Str1) <> Length(Str2) THEN { If different lengths then they }
  263.    Result := FALSE                     { must be different.             }
  264.   ELSE
  265.    BEGIN
  266.     StrPos := 0;                { Initialize 'StrPos' to 0.             }
  267.     REPEAT                      { Loop until every char checked.        }
  268.      INC(StrPos);               { Point to next char.                   }
  269.      IF UpCase(Str1[StrPos]) <> UpCase(Str2[StrPos]) THEN
  270.       BEGIN
  271.        Result := FALSE;         { If there not the same then return     }
  272.                                 { a FALSE result.                       }
  273.        StrPos := Length(Str2);  { Now set loop exit condition.          }
  274.       END;
  275.     UNTIL StrPos = Length(Str2);
  276.    END;
  277.  
  278.   Compare := Result;            { Return proper result.                 }
  279. END;{Compare}
  280.  
  281. FUNCTION Arr2String( VAR Arr; Len :BYTE ) :STRING;
  282.                          { Routine to convert 'Len' bytes of the array  }
  283.                          { 'Arr' into a string.                         }
  284. VAR
  285.    Result :STRING;              { Holds function result.                }
  286. BEGIN
  287.   MOVE(Arr,Result[1],Len);      { Move bytes into our result string.    }
  288.   Result[0] := CHR(Len);        { Set string length byte.               }
  289.  
  290.   Arr2String := Result;         { Return proper result.                 }
  291. END;{Arr2String}
  292.  
  293. FUNCTION Fmt( Info :WORD ) :STRING;
  294.                          { Routine to create a String with info int the }
  295.                          { format '00'.                                 }
  296. VAR
  297.    Temp :STRING;                { Hold temporary string info.           }
  298. BEGIN
  299.   Str(Info,Temp);               { Convert info to a string.             }
  300.   IF Length(Temp) = 1 THEN      { if its only a single digit then add   }
  301.     Fmt := '0'+Temp             { leading zero.                         }
  302.   ELSE
  303.     Fmt := Temp;
  304. END;{Fmt}
  305.  
  306. FUNCTION TimeStr :STRING;
  307. VAR
  308.    Hour,Min,Sec,Sec100 :WORD;   { Holds temporary time info.            }
  309.    Year,Mon,Day,DoWeek :WORD;   { Holds temporary date info.            }
  310.    TempTime :STRING;            { Holds temporary TimeStr.              }
  311. BEGIN
  312.   GetDate(Year,Mon,Day,DoWeek);
  313.   TempTime := Fmt(Mon)+'-'+Fmt(Day)+'-'+Fmt(Year-1900)+' at ';
  314.   GetTime(Hour,Min,Sec,Sec100); { Get Current Time.                     }
  315.   IF Hour >= 12 THEN
  316.     TempTime := TempTime+Fmt(Hour-12)+':'+Fmt(Min)+'pm'
  317.   ELSE
  318.     IF Hour = 0 THEN
  319.       TempTime := TempTime+'12:'+Fmt(Min)+'am'
  320.     ELSE
  321.       TempTime := TempTime+Fmt(Hour)+':'+Fmt(Min)+'pm';
  322.   TimeStr := TempTime;
  323. END;
  324.  
  325. FUNCTION GetOrigin( Chunks :WORD ) :STRING;
  326.                          { Routine to get message origin line if any.   }
  327. VAR
  328.    Result :STRING;              { Holds function result.                }
  329.    CurChnk:WORD;                { Holds current chunk being read.       }
  330.    BufPos :WORD;                { Position within buffer.               }
  331.    Temp   :STRING;
  332.    NumRead:WORD;                { Holds number of bytes read from file. }
  333.    Buffer :ARRAY[1..128] OF CHAR;{ Buffer for info read from file.      }
  334.    TareLin:BOOLEAN;             { Holds whether or not we've past the   }
  335.                                 { tear line.                            }
  336. BEGIN
  337.   Result := '';                 { Clear result.                         }
  338.   Temp := '';                   { Clear temporary storage space.        }
  339.   TareLin := FALSE;             { Default to FALSE.                     }
  340.   FOR CurChnk := 1 TO Chunks-1 DO { Loop through all the 128 byte chunks.}
  341.    BEGIN
  342.     BlockRead(MessDat,Buffer,128,NumRead); { Read message info.         }
  343.     FOR BufPos := 1 TO 128 DO
  344.      BEGIN
  345.       IF Buffer[BufPos] = #227 THEN
  346.        BEGIN
  347.         IF Temp = '---' THEN
  348.          TareLin := TRUE
  349.         ELSE
  350.          IF TareLin AND (Temp <> PadStr(Right,'',Length(Temp),' ')) THEN
  351.           Result := Temp;
  352.         Temp := ''
  353.        END
  354.       ELSE
  355.        Temp := Temp + Buffer[BufPos];
  356.      END;
  357.    END;
  358.  
  359.   IF (Result = '') OR (Pos('ILink:',Result) = 0) THEN
  360.    Result := ' ■ Origin Line Unavailable ■ ';
  361.  
  362.   GetOrigin := Result;          { Return proper result.                 }
  363. END;
  364.  
  365. PROCEDURE ReadMsgs;
  366.                          { Routine to read Messages and save new members}
  367.                          { to disk.                                     }
  368. VAR
  369.   MessBuf :MsgDHdr;             { Holds header info read from file.     }
  370.   InfPos  :WORD;                { Loop variable for searching 'FileInf'.}
  371.   CurMess :WORD;                { Loop variable for reading messages.   }
  372.   NumRead :WORD;                { Holds number of bytes read from file. }
  373.   Found   :BOOLEAN;             { Holds whether or not name was already }
  374.                                 { read.                                 }
  375.   FoundPos:WORD;                { Holds position in array name was found.}
  376.   Temp    :STRING;              { Holds temporary string info.          }
  377.   Chunks  :WORD;                { Holds number of 128 byte chunks message}
  378.                                 { takes up in file.                     }
  379.   ErrCode :WORD;                { Holds error codes returned from 'Val'.}
  380.   Create  :BOOLEAN;
  381. BEGIN
  382.   Create  := NOT fExist(OutFile);
  383.   IF NumFound = 0 THEN NumFound := 1;
  384.   Assign(MessDat,WorkDir+'\MESSAGES.DAT');{ Assign handle to message file.}
  385.   {$I-}                         { Turn I/O checking off.                }
  386.   Reset(MessDat,1);             { Open file for reading.                }
  387.   {$I+}                         { Turn I/O checking back on.            }
  388.   FOR CurMess := 1 TO NumMess DO { Loop through all the messages.       }
  389.    BEGIN
  390.      Seek(MessDat,fOfs[CurMess]);{ Move to current message position.    }
  391.      BlockRead(MessDat,MessBuf,SizeOf(MessBuf),NumRead); { Read Header. }
  392.      FOR InfPos := 1 TO NumFound DO
  393.       BEGIN
  394.        Found := Compare(FInf[InfPos].Name,Arr2String(MessBuf.MFrom,25));
  395.        IF Found THEN
  396.         InfPos := NumFound;
  397.       END;
  398.      IF NOT Found THEN
  399.       BEGIN
  400.        INC(NewMems);            { Increase number of new members.       }
  401.        IF Create AND (NumFound = 1) THEN
  402.         BEGIN
  403.           NumFound := 0;
  404.           Create := FALSE;
  405.         END;
  406.        INC(NumFound);           { Increase number found.                }
  407.  
  408.        FInf[NumFound].Name := Arr2String(MessBuf.MFrom,25);
  409.        Temp := Arr2String(MessBuf.NChunks,6);
  410.        RemoveSpaces(Temp);
  411.        Val(Temp,Chunks,ErrCode);
  412.        FInf[NumFound].Origin := GetOrigin(Chunks);
  413.       END;
  414.    END;
  415.   Close(MessDat);               { Close message file.                   }
  416. END;{ReadMsgs}
  417.  
  418. PROCEDURE SaveList;
  419.                          { Routine to write our list to the list file.  }
  420. VAR
  421.    ListPos :WORD;               { Position withing list being written.  }
  422. BEGIN
  423.   Assign(OutHan,OutFile);       { Assign handle to file name.           }
  424.   {$I-}                         { I/O off.                              }
  425.   Rewrite(OutHan);              { Open file for writing.                }
  426.   {$I+}                         { I/O on.                               }
  427.   IF IOResult <> 0 THEN         { If there was an error.                }
  428.    Writeln('-Error! Unable to Open ',OutFile,^G)
  429.   ELSE
  430.    BEGIN
  431.     Writeln(OutHan,'');         { Write a blank line to file.           }
  432.     Writeln(OutHan,'/*'+PadStr(Right,'',75,'-')+'*/');
  433.  
  434.     Writeln(OutHan,'                         Conference [',ParamStr(2),
  435.                    '] Members list.');
  436.     Writeln(OutHan,PadStr(Right,'',24,' ')+'Last Change '+TimeStr);
  437.     Writeln(OutHan,'/*'+PadStr(Right,'',75,'-')+'*/');
  438.     FOR ListPos := 1 TO NumFound DO
  439.      BEGIN
  440.       Writeln(OutHan,'');       { Writeln a blank line.                 }
  441.       Writeln(OutHan,'User : '+FInf[ListPos].Name); { Writeln user name.}
  442.       Writeln(OutHan,FInf[ListPos].Origin); { Write users origin line.  }
  443.      END;
  444.     Close(OutHan);                { Close file.                           }
  445.    END;
  446. END;{SaveList}
  447.  
  448. PROCEDURE ReadList;
  449.                          { Routine to read in the conf members list.    }
  450. VAR
  451.    InFile :TEXT;                { Text handle for conference list.      }
  452.    Temp   :STRING;              { Holds string read from file.          }
  453. BEGIN
  454.   NumFound := 0;
  455.   Assign(InFile,OutFile);       { Assign handle to file name.           }
  456.   {$I-}                         { I/O checking off.                     }
  457.   Reset(Infile);                { Open file for reading.                }
  458.   {$I+}                         { I/O checking on.                      }
  459.   WHILE (NOT EOF(InFile)) AND (NumFound <500) DO
  460.    BEGIN
  461.     ReadLn(InFile,Temp);        { Read a line from the file.            }
  462.     IF Copy(Temp,1,7) = 'User : ' THEN { If its the user name then.     }
  463.      BEGIN                      { Save Name to array and read origin.   }
  464.       INC(NumFound);
  465.       FInf[NumFound].Name := Copy(Temp,8,Length(Temp));
  466.       ReadLn(InFile,FInf[NumFound].Origin);
  467.      END;
  468.    END;
  469.   IF NumFound = 0 THEN
  470.    NumFound := 1;
  471.   Close(InFile);                { Close file.                           }
  472. END;{ReadList}
  473.  
  474. PROCEDURE SortList;
  475.                          { Routine to sort the list of conference       }
  476.                          { members using a simple bubble sort.          }
  477. VAR
  478.    Temp  :MessInfType;          { Temporary record for swapping.        }
  479.    Index1,Index2:WORD;          { Sort loop variables.                  }
  480. BEGIN
  481.   FOR Index1 := NumFound DOWNTO 1 DO
  482.    FOR Index2 := 2 TO Index1 DO
  483.     IF FInf[Index2-1].Name > FInf[Index2].Name THEN
  484.      BEGIN
  485.       Temp := FInf[Index2];
  486.       FInf[Index2] := FInf[Index2-1];
  487.       FInf[Index2-1] := Temp;
  488.      END;
  489. END;{SortList}
  490.  
  491. BEGIN
  492.   Writeln(ProgTitle);           { Display program title.                }
  493.  
  494.   IF (ParamCount <> 2) OR NotNumber(ParamStr(2)) THEN
  495.                                 { If wrong command argument show proper }
  496.     Syntax_Error                { syntax to use.                        }
  497.   ELSE
  498.    BEGIN
  499.     InitVars;                   { Initialize variables.                 }
  500.     IF fExist(QWKName) THEN     { If it exists begin processing.        }
  501.      BEGIN
  502.       Writeln('-Opening Packet');
  503.       OpenPacket(QWKName);      { Open mail packet.                     }
  504.       IF fExist(WorkDir+'\'+PadStr(Left,ParamStr(2),3,'0')+'.NDX') THEN
  505.        BEGIN                    { IF there are any Messages in conf then}
  506.                                 { Attempt to read NDX files.            }
  507.         Writeln('-Reading NDX file');
  508.  
  509.         IF ReadNDX THEN         { IF there is no error, read messages.  }
  510.          BEGIN
  511.  
  512.           IF fExist(OutFile) THEN{ IF Conf list already exist then read.}
  513.            BEGIN
  514.             Writeln('-Reading ',OutFile);
  515.             ReadList;
  516.  
  517.            END;
  518.  
  519.           Writeln('-Reading Messages in conference [',ParamStr(2),']');
  520.           ReadMsgs;
  521.  
  522.           IF NewMems > 0 THEN
  523.            BEGIN
  524.  
  525.             IF fExist(OutFile) THEN
  526.              BEGIN
  527.               Writeln('-Renaming ',OutFile,' to ',Copy(OutFile,1,8)+'.BAK');
  528.  
  529.               IF fExist(Copy(OutFile,1,8)+'.BAK') THEN
  530.                BEGIN
  531.                 Assign(OutHan,Copy(OutFile,1,8)+'.BAK');
  532.                 Erase(OutHan);
  533.                END;
  534.  
  535.               Assign(OutHan,OutFile);
  536.               Rename(OutHan,Copy(OutFile,1,8)+'.BAK');
  537.              END
  538.             ELSE
  539.              BEGIN
  540.               Writeln('-Creating ',OutFile);
  541.               Assign(OutHan,OutFile);
  542.               {$I-}
  543.               Rewrite(OutHan);
  544.               {$I+}
  545.               Close(OutHan);
  546.              END;
  547.             Writeln('-Sorting member list');
  548.             SortList;
  549.             Writeln('-Saving ',NewMems,
  550.                     ' new members for a total of ',NumFound,' members');
  551.             SaveList;
  552.            END
  553.           ELSE
  554.            Writeln('-No new members found');
  555.          END
  556.         ELSE
  557.          Writeln('-Error reading NDX file',^G);
  558.        END
  559.       ELSE                      { Other wise let user know its not there.}
  560.        Writeln('-NDX file for conference [',ParamStr(2),
  561.                '] does not exist. No new messages?'^G);
  562.  
  563.       Writeln('-Deleteing Work Directory');
  564.       DelWorkDir;               { Delete Work Directory.                }
  565.       {$I-}                     { Turn I/O checking off.                }
  566.       RMDir(WorkDir);           { Remove work Directory.                }
  567.       {$I+}                     { Turn I/O checking on.                 }
  568.       IF IOResult <> 0 THEN     { If and error occurs then              }
  569.       Writeln('Error Removing work directory.',^G);
  570.  
  571.      END
  572.     ELSE                        { .... Otherwise ......                 }
  573.      BEGIN                      { Show error message and beep.          }
  574.       Writeln(^G,'Cannot find ',QWKName);
  575.       Writeln('Tracking aborted!!');
  576.      END;
  577.    END;
  578. END.{NMembers}
  579. {***********************************************************************}
  580.